import cgi

from google.appengine.api import users, datastore_types
from google.appengine.ext import db

from gaeo.controller import BaseController

from model.issue import Issue
from model.status import Status

class IssuePropertyConverter(object):
    @staticmethod
    def make_url(url):
        return db.Link(url)

    @staticmethod
    def make_title(title):
        return title.strip()

    @staticmethod
    def make_comment(comment):
        return comment

    @staticmethod
    def make_status(status_id):
        return Status.get(status_id) if status_id and status_id != 'None' else None

    @staticmethod
    def str_status(status):
        return status if status is not None else 'None'

    @staticmethod
    def make_tags(tags):
        return map(lambda s: s.strip(), tags.split(',')) if tags else []    

    @staticmethod
    def str_tags(tags):
        return ', '.join(tags)

class IssueController(BaseController):
    def before_action(self):
        if not users.get_current_user():
            self.redirect(users.create_login_url('/'))

        self.status_list = Status.all().filter("owner =", users.get_current_user())

    def create(self):
        if users.get_current_user():
            r = Issue(
                url = IssuePropertyConverter.make_url(self.params.get('url')),
                title = IssuePropertyConverter.make_title(self.params.get('title')),
                comment = IssuePropertyConverter.make_comment(self.params.get('comment')),
                status = IssuePropertyConverter.make_status(self.params.get('status')),
                tags = IssuePropertyConverter.make_tags(self.params.get('tags')),
            )
            r.put()
        self.redirect('/issue')

    def destroy(self):
        r = Issue.get(self.params.get('id'))
        if r is not None:
            if r.owner == users.get_current_user():
                r.delete()
        self.redirect('/issue')

    def edit(self):
        r = Issue.get(self.params.get('id'))
        if r:
            for prop in Issue.properties():
                conv = getattr(IssuePropertyConverter, 'str_' + prop, lambda x: x)
                if callable(conv):
                    setattr(self, prop, conv(getattr(r, prop)))
        else:
            self.redirect('/issue')

    def index(self):
        query = Issue.all()
        query.filter('owner =', users.get_current_user())
        self.result = query.fetch(limit=1000)

    def new(self):
        pass

    def query(self):
        if self.params.get('backend', '') in ['accurate', 'precise']:
            keys = []
            values = ()
            for prop in Issue.properties():
                value = self.params.get(prop, None)
                if value: # bypass 'None' and empty values.
                    keys.append('%s = :%d' % (prop, len(keys)+1))
                    values += (cgi.escape(value),)
        
            self.result = Issue.gql('WHERE ' + ' AND '.join(keys), *values).fetch(100) if keys else []
        else:
            self.keyword = self.params.get('keyword', '')
            self.result = Issue.all().search(self.keyword)

    def search(self):
        self.advanced = bool(self.params.get('id', '').lower() == 'advanced')

    def show(self):
        r = Issue.get(self.params.get('id'))
        if r:
            for prop in Issue.properties():
                conv = getattr(IssuePropertyConverter, 'str_' + prop, lambda x: x)
                if callable(conv):
                    setattr(self, prop, conv(getattr(r, prop)))
        else:
            self.redirect('/issue')

    def update(self):
        r = Issue.get(self.params.get('id'))
        if r.owner == users.get_current_user():
            for prop in Issue.properties():
                if prop in self.params:
                    conv = getattr(IssuePropertyConverter, 'make_' + prop, lambda x: x)
                    if callable(conv):
                        setattr(r, prop, conv(self.params.get(prop)))
            r.put()
        self.redirect('/issue/show/%s' % (r.key()))
